/*
 *  Name		: tc_1.c
 *	Author	 	: Tigran Papazyan
 *  Created on	: Dec 6, 2010
 *  Copyright   : Copyright Antel Systems
 *  Description : Timer 1 Driver
 */

#include <avr32/io.h>
#if defined (__GNUC__)
#include "intc.h"
#endif
#include "compiler.h"
#include "board.h"
#include "power_clocks_lib.h"
#include "clocks.h"
#include "gpio.h"
#include "tc.h"
#include "usart.h"
#include "tc_1.h"


#define TC_CHANNEL    1

#define TIMER_ONE_MILISEC		((FMCK_HZ>>7)/1000)
#define TIMER_10_MICROSEC		((FMCK_HZ>>1)/100000)
#define TIMER_100_MICROSEC		((FMCK_HZ>>1)/10000)

#  define TC                  (&AVR32_TC)
#  define TC_IRQ_GROUP        AVR32_TC_IRQ_GROUP
#  define TC_IRQ              AVR32_TC_IRQ1
#  define FPBA                        FOSC0

#if !defined(TC)             || \
    !defined(TC_IRQ_GROUP)      || \
    !defined(TC_IRQ)
#  error The TC preprocessor configuration to use in this example is missing.
#endif

// To specify we have to print a new time
volatile U64 tc1_tick = 0;

/**************************************************************************************/
#if defined (__GNUC__)
__attribute__((__interrupt__))
#elif defined (__ICCAVR32__)
#pragma handler = EXAMPLE_TC_IRQ_GROUP, 1
__interrupt
#endif
static void TC1_irq(void)
{
	unsigned short clear ;
  // Increment the ms seconds counter
  tc1_tick++;
  // Clear the interrupt flag. This is a side effect of reading the TC SR.
  //tc_read_sr(TC, TC_CHANNEL);
  clear = TC->channel[1].sr ;
  // specify that an interrupt has been raised
}
/**************************************************************************************/

/**************************************************************************************/
void TC1_init(void)
{
  volatile avr32_tc_t *tc = TC;

  // Options for waveform genration.
  static const tc_waveform_opt_t WAVEFORM_OPT =
  {
    .channel  = TC_CHANNEL,                        // Channel selection.

    .bswtrg   = TC_EVT_EFFECT_NOOP,                // Software trigger effect on TIOB.
    .beevt    = TC_EVT_EFFECT_NOOP,                // External event effect on TIOB.
    .bcpc     = TC_EVT_EFFECT_NOOP,                // RC compare effect on TIOB.
    .bcpb     = TC_EVT_EFFECT_NOOP,                // RB compare effect on TIOB.

    .aswtrg   = TC_EVT_EFFECT_NOOP,                // Software trigger effect on TIOA.
    .aeevt    = TC_EVT_EFFECT_NOOP,                // External event effect on TIOA.
    .acpc     = TC_EVT_EFFECT_NOOP,                // RC compare effect on TIOA: toggle.
    .acpa     = TC_EVT_EFFECT_NOOP,                // RA compare effect on TIOA: toggle (other possibilities are none, set and clear).

    .wavsel   = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,// Waveform selection: Up mode with automatic trigger(reset) on RC compare.
    .enetrg   = FALSE,                             // External event trigger enable.
    .eevt     = 0,                                 // External event selection.
    .eevtedg  = TC_SEL_NO_EDGE,                    // External event edge selection.
    .cpcdis   = FALSE,                             // Counter disable when RC compare.
    .cpcstop  = FALSE,                             // Counter clock stopped with RC compare.

    .burst    = FALSE,                             // Burst signal selection.
    .clki     = FALSE,                             // Clock inversion.
    .tcclks   = TC_CLOCK_SOURCE_TC2                // Internal source clock 3, connected to fPBA / 2.
  };

  static const tc_interrupt_t TC_INTERRUPT =
  {
    .etrgs = 0,
    .ldrbs = 0,
    .ldras = 0,
    .cpcs  = 1,
    .cpbs  = 0,
    .cpas  = 0,
    .lovrs = 0,
    .covfs = 0
  };

  Disable_global_interrupt();

  // The INTC driver has to be used only for GNU GCC for AVR32.
#if defined (__GNUC__)
  // Initialize interrupt vectors.
//  INTC_init_interrupts();

  // Register the RTC interrupt handler to the interrupt controller.
  INTC_register_interrupt(&TC1_irq, TC_IRQ, AVR32_INTC_INT0);
#endif

  // Initialize the timer/counter.
  tc_init_waveform(tc, &WAVEFORM_OPT);         // Initialize the timer/counter waveform.

  // Set the compare triggers.
  // Remember TC counter is 16-bits, so counting second is not possible with fPBA = 12 MHz.
  // We configure it to count ms.
  // We want: (1/(fPBA/8)) * RC = 0.001 s, hence RC = (fPBA/8) / 1000 = 1500 to get an interrupt every 1 ms.
  tc_write_rc(tc, TC_CHANNEL, TIMER_100_MICROSEC*1); // Set RC value.

  tc_configure_interrupts(tc, TC_CHANNEL, &TC_INTERRUPT);

  // Start the timer/counter.
  tc_start(tc, TC_CHANNEL);                    // And start the timer/counter.

  Enable_global_interrupt();
}
/**************************************************************************************/

/**************************************************************************************/
Timer_Tik TC1_Get_us(void)
{
	return tc1_tick*100 ;
}
/**************************************************************************************/

/**************************************************************************************/
unsigned char TC1_IF_us(Timer_Tik Old_tik , Timer_Tik us)
{
	if(tc1_tick*100-Old_tik >= us)
		return TRUE ;
	else
		return FALSE ;
}
/**************************************************************************************/

/**************************************************************************************/
void TC1_delay_us(U64 us)
{
	U64 tik = TC1_Get_us();
	while(us > TC1_Get_us() - tik);
}
/**************************************************************************************/

